#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/6/9 9:07
# @Author : linjinting
# @Project : custom_protocol
# @File : __init__.py.py
# @Software: PyCharm

from protocol_message._struct import YXStruct, YKStruct, split_int_to_simple_byte
from datetime import datetime
from ctypes import c_ubyte, sizeof

YX_SIZE = sizeof(YXStruct)
YK_SIZE = sizeof(YKStruct)
c_ubyte_array_2 = c_ubyte * 2
c_ubyte_array_4 = c_ubyte * 4

HEADER_ARRAY = c_ubyte_array_2(0xeb, 0x90)
VERSION = 0x01
_TYPE_YX = 0x04
_TYPE_YK_ALLOW = 0x05
_TYPE_YK_REJECT = 0x06
LENGTH_ARRAY = c_ubyte_array_2(13, 0)
YK_LENGTH_ARRAY = c_ubyte_array_2(11, 0)
# ID
# DATA_TYPE_YX = 0X04
# DATA_TYPE_YX_ALLOW = 0X05
# DATA_TYPE_YX_REJECT = 0X06
STATE_0 = 0x00
STATE_1 = 0x01
# TIME_ARRAY
# MS_ARRAY
# PARITY
type_map = {4: _TYPE_YX, 5: _TYPE_YK_ALLOW, 6: _TYPE_YK_REJECT}
type_str_format_map = {_TYPE_YX: '[YX]', _TYPE_YK_ALLOW: '[YK-allow]', _TYPE_YK_REJECT: '[YK-reject]'}
value_str_format_map = {0: '[0]', 1: '[1]', 128: '[confirm][0]', 129: '[confirm][1]'}
channel_struct_map = {'yx': YXStruct, 'yk': YKStruct}
channel_struct_size_map = {'yx': YX_SIZE, 'yk': YK_SIZE}


def get_time_array():
    # global bytes_array
    ts = datetime.now().timestamp()
    time_ = int(ts)

    bytes_array = split_int_to_simple_byte(list(), time_)
    bytes_array.reverse()
    TIME_ARRAY = c_ubyte_array_4(*bytes_array)
    ms = int((ts - time_) * 1000)
    bytes_array = split_int_to_simple_byte(list(), ms, 1)
    bytes_array.reverse()
    MS_ARRAY = c_ubyte_array_2(*bytes_array)
    return TIME_ARRAY, MS_ARRAY
    # TIME_ARRAY =


def get_struct_for_channel(channel, data):
    # print(channel)
    return channel_struct_map.get(channel)(data)


def parse(data, channel):
    try:
        JZS = get_struct_for_channel(channel, data)
    except (ValueError, KeyError)as e:
        return e.__str__()

    if not JZS.check_parity():
        return 'parity error'
    return JZS


def parse_to_msg(data, channel, side):
    """
    jz protocol message parse
    :param data:
    :param channel:
    :param side:
    :return:
    """
    JZS = parse(data, channel)
    if isinstance(JZS, str):
        msg = '[%s] parse struct %s' % (side, JZS)
        return msg
    if channel == 'yx':
        time_str = '%s.%s' % (datetime.fromtimestamp(JZS.time).strftime('%Y-%m-%d %H:%M:%S'), JZS.ms)
    else:
        time_str = datetime.fromtimestamp(JZS.time).strftime('%Y-%m-%d %H:%M:%S')
    msg = '[%s] %s %s message\n' \
          '[ID]:%s, [value]:%s, [Time]:%s' % \
          (side, type_str_format_map.get(JZS.dataType, JZS.dataType), value_str_format_map.get(JZS.state),
           JZS.ID, hex(JZS.state), time_str)

    return msg


def produce_yx(ID, commandType, state):
    timeArray, msArray = get_time_array()
    IDArray = split_int_to_simple_byte(list(), ID)
    IDArray.reverse()
    JZS = YXStruct()
    JZS.headerArray = HEADER_ARRAY
    JZS.version = VERSION
    JZS.commandType = type_map.get(commandType, 0)
    JZS.lengthArray = LENGTH_ARRAY
    JZS.IDArray = c_ubyte_array_4(*IDArray)
    JZS.dataType = type_map.get(commandType, 0)
    JZS.state = state
    JZS.timeArray = timeArray
    JZS.msArray = msArray
    JZS.set_parity()
    # print(JZS.ms)
    return JZS.get_string_at()


def produce_yk(ID, commandType, state):
    timeArray, msArray = get_time_array()
    IDArray = split_int_to_simple_byte(list(), ID)
    IDArray.reverse()
    JZS = YKStruct()
    JZS.headerArray = HEADER_ARRAY
    JZS.version = VERSION
    JZS.commandType = type_map.get(commandType, 0)
    JZS.lengthArray = YK_LENGTH_ARRAY
    JZS.IDArray = c_ubyte_array_4(*IDArray)
    JZS.dataType = type_map.get(commandType, 0)
    JZS.state = state
    JZS.timeArray = timeArray
    JZS.set_parity()
    # print(JZS.state)
    return JZS.get_string_at()


if __name__ == '__main__':
    print(sizeof(YXStruct))
    # time_, ms = get_time_array()
    # print(list(time_), list(ms))
    # timeA = (times >> 24)
    # timeA_L = timeA << 24
    # print('-----------------------------')
    # print(timeA_L)
    # timeB = (times - timeA_L) >> 16
    # print(timeB)
    # timeB_L = timeB << 16
    # print(timeB_L)
    # timeC = (times - timeA_L - timeB_L) >> 8
    # print(timeC)
    # timeC_L = timeC << 8
    # print(timeC_L)
    # timeD = (times - timeA_L - timeB_L - timeC_L)
    # print(timeA, timeB, timeC, timeD)

    # ms = int((ts - times) * 1000)
    # print(ms)
